// config/config.go
package config

import (
	"fmt"
	"gopkg.in/yaml.v3"
	"os"
	"path/filepath"
	"strconv"
)

type AppConfig struct {
	Env  string `yaml:"env"`
	Port int    `yaml:"port"`
	Name string `yaml:"name"`
}

type DatabaseConfig struct {
	Enabled      bool   `yaml:"enabled"`
	Host         string `yaml:"host"`
	Port         int    `yaml:"port"`
	User         string `yaml:"user"`
	Password     string `yaml:"password"`
	DataBaseName string `yaml:"database_name"`
	MaxOpenConns int    `yaml:"max_open_conns"`
	MaxIdleConns int    `yaml:"max_idle_conns"`
}

type DouyinConfig struct {
	AppID             string `yaml:"app_id"`
	AppSecret         string `yaml:"app_secret"`
	APIBaseURL        string `yaml:"api_base_url"`
	APIWebcastBaseURL string `yaml:"api_webcast_base_url"`
}

type GameConfig struct {
	Team string `yaml:"team"`
	Job  string `yaml:"job"`
}

type Config struct {
	App      AppConfig      `yaml:"app"`
	Database DatabaseConfig `yaml:"database"`
	Douyin   DouyinConfig   `yaml:"douyin"`
	Game     GameConfig     `yaml:"game"`
}

var globalConfig *Config

// 全局配置获取方法
func Get() *Config {
	if globalConfig == nil {
		panic("config not initialized")
	}
	return globalConfig
}

// 初始化配置（应在main函数中尽早调用）
func Init(env string) error {
	// 1. 确定环境
	if env == "" {
		env = getEnv("APP_ENV", "dev")
	}

	// 2. 加载基础配置
	basePath := getConfigPath("config.yaml")
	baseCfg, err := loadConfigFile(basePath)
	if err != nil {
		return fmt.Errorf("failed to load base config: %v", err)
	}

	// 3. 加载环境特定配置
	envPath := getConfigPath(fmt.Sprintf("config.%s.yaml", env))
	envCfg, err := loadConfigFile(envPath)
	if err != nil && !os.IsNotExist(err) {
		return fmt.Errorf("failed to load env config: %v", err)
	}

	// 4. 合并配置（环境配置覆盖基础配置）
	mergedCfg := mergeConfigs(baseCfg, envCfg)

	// 5. 环境变量覆盖
	applyEnvOverrides(mergedCfg)

	// 6. 设置默认值
	setDefaults(mergedCfg)

	// 7. 验证配置
	if err := validateConfig(mergedCfg); err != nil {
		return err
	}

	globalConfig = mergedCfg
	return nil
}

// 内部实现细节
func getConfigPath(filename string) string {
	// 优先尝试当前目录
	localPath := filepath.Join(".", "configs", filename)
	if _, err := os.Stat(localPath); err == nil {
		return localPath
	}

	// 尝试可执行文件目录
	exePath, _ := os.Executable()
	return filepath.Join(filepath.Dir(exePath), "configs", filename)
}

func loadConfigFile(path string) (*Config, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}

	var cfg Config
	if err := yaml.Unmarshal(data, &cfg); err != nil {
		return nil, fmt.Errorf("invalid YAML in %s: %v", path, err)
	}
	return &cfg, nil
}

func mergeConfigs(base, override *Config) *Config {
	// 实际实现需要根据字段合并，这里简化处理
	// 可以使用第三方库如github.com/imdario/mergo
	if override == nil {
		return base
	}
	return &Config{
		App:      mergeAppConfig(base.App, override.App),
		Database: mergeDBConfig(base.Database, override.Database),
		Douyin:   mergeDouyinConfig(base.Douyin, override.Douyin),
		Game:     mergeGameConfig(base.Game, override.Game),
	}
}

func setDefaults(cfg *Config) {
	// 应用配置
	if cfg.App.Port == 0 {
		cfg.App.Port = 8080
	}

	// 数据库配置
	if cfg.Database.Port == 0 {
		cfg.Database.Port = 3306
	}
	if cfg.Database.MaxOpenConns == 0 {
		cfg.Database.MaxOpenConns = 100
	}
	if cfg.Database.MaxIdleConns == 0 {
		cfg.Database.MaxIdleConns = 20
	}
}

func validateConfig(cfg *Config) error {
	if cfg.Database.Enabled {
		if cfg.Database.Host == "" {
			return fmt.Errorf("database host is required")
		}
		if cfg.Database.User == "" {
			return fmt.Errorf("database user is required")
		}
	}
	return nil
}

func applyEnvOverrides(cfg *Config) {
	// 应用配置覆盖
	if port := getEnv("APP_PORT", ""); port != "" {
		if p, err := strconv.Atoi(port); err == nil {
			cfg.App.Port = p
		}
	}

	// 数据库配置覆盖
	cfg.Database.Host = getEnv("DB_HOST", cfg.Database.Host)
	cfg.Database.User = getEnv("DB_USER", cfg.Database.User)
	cfg.Database.Password = getEnv("DB_PASSWORD", cfg.Database.Password)

	// 抖音配置覆盖
	cfg.Douyin.AppID = getEnv("DY_APP_ID", cfg.Douyin.AppID)
	cfg.Douyin.AppSecret = getEnv("DY_APP_SECRET", cfg.Douyin.AppSecret)
}

// 辅助函数
func getEnv(key, defaultValue string) string {
	if value, exists := os.LookupEnv(key); exists {
		return value
	}
	return defaultValue
}

// 合并逻辑示例（需要为每个配置结构实现）
func mergeAppConfig(base, override AppConfig) AppConfig {
	if override.Port != 0 {
		base.Port = override.Port
	}
	if override.Env != "" {
		base.Env = override.Env
	}
	return base
}

func mergeDBConfig(base, override DatabaseConfig) DatabaseConfig {
	if override.Enabled {
		base.Enabled = override.Enabled
	}
	if override.Host != "" {
		base.Host = override.Host
	}
	if override.Port != 0 {
		base.Port = override.Port
	}
	if override.User != "" {
		base.User = override.User
	}
	if override.Password != "" {
		base.Password = override.Password
	}
	if override.DataBaseName != "" {
		base.DataBaseName = override.DataBaseName
	}
	if override.MaxOpenConns != 0 {
		base.MaxOpenConns = override.MaxOpenConns
	}
	if override.MaxIdleConns != 0 {
		base.MaxIdleConns = override.MaxIdleConns
	}
	return base
}

func mergeDouyinConfig(base, override DouyinConfig) DouyinConfig {
	if override.AppID != "" {
		base.AppID = override.AppID
	}
	if override.AppSecret != "" {
		base.AppSecret = override.AppSecret
	}
	if override.APIBaseURL != "" {
		base.APIBaseURL = override.APIBaseURL
	}
	if override.APIWebcastBaseURL != "" {
		base.APIWebcastBaseURL = override.APIWebcastBaseURL
	}
	return base
}

func mergeGameConfig(base, override GameConfig) GameConfig {
	if override.Team != "" {
		base.Team = override.Team
	}
	if override.Job != "" {
		base.Job = override.Job
	}
	return base
}
